#!/usr/local/bin/perl -w
use strict;
use utf8;

use Log::Syslog::Fast ':all';
use CGI::Fast;
use JSON::XS;
use HTTP::Parser::XS qw(parse_http_request parse_http_response HEADERS_AS_HASHREF);
use IO::Socket::INET;

my ($logger,$addr,$port,$host,$path,$config);
my $rid = 1000;

read_config();
if(1){
	run();
}else{
	work("привет","123");
}


sub read_config {
	local *F;
	open F,"../config.cfg";
	local $/;
	my $str = <F>;
	close F;
	eval "\$config = {".$str."}";
	if($@){
		die $@;
	}
	$logger = Log::Syslog::Fast->new(LOG_UNIX, "/dev/log", 0, LOG_LOCAL0, LOG_INFO, $config->{chat}{logger}, "reg.pl");
	$addr = $config->{chat}{addr};
	$port = $config->{chat}{port};
	$path = $config->{chat}{path};
	$host = $config->{chat}{host};
}

sub debug{
	$logger->send($_[0]);
}
sub send_message {
	my ($command,$message) = @_;
	my $socket = IO::Socket::INET->new(
				PeerAddr => $addr,
				PeerPort => $port,
				Type     => SOCK_STREAM,
				LocalAddr => "127.0.0.1",
			);
	unless($socket){
		return 0;
	}

	#$message->{ts} = ts();
	$message->{rid} = $rid++;
	$message->{login} = "admin";
	$message->{pass} = "12345";

	my $body = encode_json($message);

	my $to_send = sprintf(
"POST %s/$command HTTP/1.1
Content-Length: %d
Host: %s
Connection: close

%s",
		$path,length($body),$host,$body);
	if(real_send($socket,$to_send) > 0){
		return "send";
	}elsif($message->{nowait}){
		return "nowait";
	}elsif(my $msg = real_recv($socket)){
		return $msg;
	}else{
		return "close";
	}
}
sub real_send {
	my ($socket,$to_send) = @_;
	my $need = length($to_send);
	while($need > 0){
		my $rs = $socket->send($to_send);
		if($rs > 0){
			$need -= $rs;
			substr($to_send,0,$rs,"");
		}else{
			return $need;
		}
	}
	return 0;
}
sub real_recv{
	my ($sock) = @_;
	my $str = "";
	while(1){
		my $buf;
		$sock->recv($buf,1024);
		if($buf){
			if(my $msg = parse_response($str .= $buf)){
				return $msg;
			}
		}else{
			return undef;
		}
	}
}
sub parse_response{
	my $full_body = shift;
	my($ret, $mv, $status, $mss, $headers) = parse_http_response($full_body, HEADERS_AS_HASHREF);
	if($ret > 0) {
		if($status == 200){
			my $body = substr($full_body,$ret);
			if($headers->{'content-length'} && $headers->{'content-length'} > length($body)){
				return 0;
			}else{
				my $msg = "json";
				eval {
					$msg = decode_json($body);
				};
				return $msg;
			}
		}else{
			return "status";
		}
	}elsif($ret == -2){
		return "response";
	}else{
		return 0;
	}
}
sub answer {
	my $str = encode_json($_[0]);
	print "Content-Type: text/json; charset=utf-8\nContent-Length: ",length($str),"\n\n",$str;
}
sub check_login {
	my ($login) = @_;
	unless($login =~ /^[ \wа-яА-Я]{3,15}$/){
		return "плохие символы в логине или неподходящая длинна $login";
	}
	unless($login =~ /^[\wа-яА-Я]/){
		return "в начале только буква";
	}
	if($login =~ /\s{2,}/){
		return "много пробелов";
	}
	if($login =~ /\s$/){
		return "пробел в конце нельзя";
	}
	if($login =~ /(.)\1\1/){
		return "много одинаковых букв подряд";
	}
	unless($login =~ /^[ а-яА-Я0-9]+$/ or $login =~ /^[ a-zA-Z0-9]+$/){
		return "только один алфавит можно в логине";
	}
	return 0;
}
sub check_pass{
	my ($pass) = @_;
	if(length($pass) > 15){
		return "очень длинный пароль";
	}
	if(length($pass) < 3){
		return "очень короткий пароль";
	}
	return 0;
}
sub work {
	my ($login,$pass,$tmp) = @_;
	unless(utf8::is_utf8($login)){
		utf8::decode($login);
	}
	unless(utf8::is_utf8($pass)){
		utf8::decode($pass);
	}
	my $error;
	if($error = check_login($login)){
		answer({error=>100,text=>$error});
	}
	elsif($error = check_pass($pass)){
		answer({error=>100,text=>$error});
	}
	else {
		$tmp = $tmp ? 1: 0;
		debug("from(".$ENV{'HTTP_X_REAL_IP'}.") login($login) pass($pass) '$tmp'");
		my $res;
		eval {
			$res = send_message("reg",{userlogin=>$login,userpass=>$pass,tmp=>$tmp});
		};
		if($res && ref $res){
			answer($res);
		}else{
			answer({error=>100,text=>$res||"fail"});
		}
	}
}
sub run{
	while(my $cgi = new CGI::Fast) {
		my ($login,$pass);
		if(($login = $cgi->param("login")) && ($pass = $cgi->param("pass"))){
			work($login,$pass,$cgi->param("tmp"));
		}else{
			answer({error=>100,text=>"nedd param"});
		}
	}
}
